<script setup lang="ts">
import Envs from "@/components/Envs.vue";
import type { Crontab, Env, Host } from "@/stores/master/types";
import { getBy, getIndexBy } from "@/utils/array";
import { setup } from "@/utils/setup.js";
import { AutorenewFilled } from "@vicons/material";
import { deepClone } from "fast-json-patch";
import {
  NButton,
  NCard,
  NDynamicInput,
  NForm,
  NFormItem,
  NIcon,
  NInput,
  NInputGroup,
  NInputGroupLabel,
  NInputNumber,
  NSpace,
} from "naive-ui";
import { v4 as uuidv4 } from "uuid";
import { ref, watchEffect } from "vue";

const { configStore, route, router } = setup();

const host = ref<Host>();

function getGlobalEnv(key: string) {
  return getBy(configStore.config!.default.host.envs, "key", key)?.value;
}

function createCrontab(): Crontab {
  return { id: uuidv4(), cron: "", script: "", envs: [], enabled: true };
}

function getHostEnv(hostEnvs: Env[], key: string) {
  const env = getBy(hostEnvs, "key", key);
  if (env?.type === "inherit") {
    return getGlobalEnv(key);
  } else if (env?.type === "custom") {
    return env.custom;
  }
}

function createHost(): Host {
  return {
    id: uuidv4(),
    token: uuidv4(),
    name: "",
    restart: 0,
    ssh: {
      privateKey: "",
      publicKey: "",
      server: { port: 0, allowedKeys: [], enabled: true },
    },
    envs: [],
    crontabs: [],
  };
}

function saveHost() {
  // TODO 验证表单数据
  const index = getIndexBy(configStore.config!.hosts, "id", host.value!.id);
  if (index !== -1) {
    configStore.config!.hosts[index] = host.value!;
  } else {
    configStore.config!.hosts.push(host.value!);
  }
  router.push({ name: "hosts" });
}

watchEffect(() => {
  const id = route.query["id"] as string | undefined;
  if (id !== undefined) {
    if (configStore.config !== undefined) {
      const value = getBy(configStore.config.hosts, "id", id);
      if (value !== undefined) {
        host.value = deepClone(value);
      }
    }
  } else {
    host.value = createHost();
  }
});
</script>

<template>
  <NForm
    style="padding: 16px 32px 16px 16px"
    label-placement="left"
    label-width="auto"
  >
    <NFormItem label="唯一标识">
      <NInput v-if="host === undefined" disabled />
      <NInput v-else v-model:value="host.id" />
    </NFormItem>
    <NFormItem label="令牌">
      <NInput v-if="host === undefined" disabled />
      <NInput v-else v-model:value="host.token" />
    </NFormItem>
    <NFormItem label="主机名">
      <NInput v-if="host === undefined" disabled />
      <NInput v-else v-model:value="host.name" />
    </NFormItem>
    <NFormItem label="SSH 私钥">
      <NInputGroup>
        <NInput v-if="host === undefined" disabled />
        <NInput v-else :value="host.ssh.privateKey" disabled />
        <NButton>
          <template #icon>
            <NIcon :component="AutorenewFilled" />
          </template>
        </NButton>
      </NInputGroup>
    </NFormItem>
    <NFormItem label="SSH 端口">
      <NInputNumber v-if="host === undefined" style="width: 100%" disabled />
      <NInputNumber
        v-else
        style="width: 100%"
        v-model:value="host.ssh.server.port"
        :min="0"
        :max="65535"
      />
    </NFormItem>
    <NFormItem label="SSH 登录密钥">
      <NSpace style="width: 100%" vertical>
        <NInput
          v-if="configStore.config !== undefined"
          v-for="allowedKey of configStore.config.default.host.ssh.server
            .allowedKeys"
          :value="allowedKey"
          disabled
        />
        <NDynamicInput v-if="host === undefined" :max="0" />
        <NDynamicInput
          v-else
          v-model:value="host.ssh.server.allowedKeys"
          show-sort-button
        />
      </NSpace>
    </NFormItem>
    <NFormItem label="环境变量">
      <NDynamicInput v-if="host === undefined" :max="0" />
      <Envs v-else v-model:value="host.envs" :get-inherit="getGlobalEnv" />
    </NFormItem>
    <NFormItem label="任务">
      <NDynamicInput v-if="host === undefined" :max="0" />
      <NDynamicInput
        v-else
        v-model:value="host.crontabs"
        :on-create="createCrontab"
        show-sort-button
      >
        <template
          #default="{ value, index }: { value: Crontab, index: number }"
        >
          <NCard size="small" hoverable>
            <template #header>
              <NInputGroup>
                <NInputGroupLabel>{{ index }}</NInputGroupLabel>
                <NInput
                  style="width: 200px"
                  v-model:value="value.cron"
                  placeholder="cron"
                />
                <NInput v-model:value="value.script" placeholder="任务名称" />
              </NInputGroup>
            </template>
            <Envs
              v-model:value="value.envs"
              :get-inherit="(key) => getHostEnv(host!.envs, key)"
            />
          </NCard>
        </template>
      </NDynamicInput>
    </NFormItem>
    <NFormItem>
      <NButton
        style="margin-left: auto"
        attr-type="button"
        :disabled="host === undefined"
        @click="saveHost"
      >
        保存
      </NButton>
    </NFormItem>
  </NForm>
</template>
